#include "main.h"
#include "websocket.h"
#include "Debug.h"
#include "error_signals.h"
#include "test.h"

int main( int argc, char *argv[] )
{	
	the_websocket = nullptr;
	// Start of error handling.	
	// This is error handling to display the stack trace of a GPF error.
	// This code has to be done at the beginning of each thread.
	error_signals::AddHandlers();
    pid_t tid = error_signals::GetThreadID();
    error_signals *error_thread = error_signals::GetThread(tid);
    if (error_thread == nullptr)
    {
      error_thread = error_signals::AddThread(tid);
    }
    volatile int val = 0;
    if (error_thread != nullptr)
    {
      error_thread->LineNumberStack = 0;
      val = setjmp(error_thread->position);
    }
    if (val != 0)
    {
	  // This code runs if there's an error.
      error_thread->DisplayErrorMessage(val); // Display a stack trace like C#.
      error_signals::RemoveHandlers();
	  if (the_websocket != nullptr) {
		  the_websocket->shutdown = true;
	  }
	  return val;
    }
	// End of error handling.
	Debug debug(__FILE__,__func__,__LINE__);
	
	the_websocket = new websocket();
	debug = __LINE__;
	int port;
	if (argc != 3) {
		printf("%s Port ServerPassword\n",argv[0]);
		printf("  starts the server listening to Port.\n");
		printf("  ServerPassword is the password to edit users/chatrooms.\n");
		printf("%s test classname\n",argv[0]);
		printf("  Runs the test for classname.\n");
		printf("%s test testnumber\n",argv[0]);
		printf("  testnumber can be from 1 to %d.\n",test::testcount());
		printf("%s test all\n",argv[0]);
		printf("  Runs all the tests.\n");
		printf("To stop the program, press CTRL C or CTRL Z.\n");
		printf("To stop the program running in the background, call kill -SIGTERM <pid>\n");
		printf("  <pid> is the process id from ps -e|grep %s\n",argv[0]);
		printf("As a last resort, use killall -9 %s\n",argv[0]);
		return 1;
	}
	debug = __LINE__;
	if (strcmp(argv[1],"test")==0) {
		port = test::runtest(argv[2]);
		return port;
	}
	debug = __LINE__;
	port = atoi(argv[1]);
	debug = __LINE__;
	if ((port <=0) || (port > 65535)) {
		printf("Error: Port must be between 1 and 65535.\n");
		return 2;
	}
	
	debug = __LINE__;
	struct lws_context_creation_info info;
	memset( &info, 0, sizeof(info) );

	info.port = port;
	info.protocols = protocols;
	info.gid = -1;
	info.uid = -1;
	
	debug = __LINE__;
	the_websocket->server_password = new datablock(argv[2]);
	debug = __LINE__;
	struct lws_context *context = lws_create_context( &info );
	debug = __LINE__;
	if (the_websocket->run_async) {
		// Start a separate thread for tasks.
		if (pthread_create(&the_websocket->task_thread,NULL,websocket::task_thread_routine,the_websocket->chatroom_tasks) != 0) {
			// Thread was unable to be created.
			the_websocket->run_async = false;
		}
	}
	debug = __LINE__;
	while( !the_websocket->shutdown )
	{
		lws_service( context, /* timeout_ms = */ 1000 );
	}
	debug = __LINE__;
	printf("%s is shutting down.\n",argv[0]);
	lws_context_destroy( context );
	delete the_websocket;
	error_thread->ReleaseThread(tid); // Error thread cleanup.	
	return 0;
}
